package cn.ilikes.tools.hbase.jpa.persistences.context;

import java.util.Stack;

import javax.persistence.EntityTransaction;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.JPAHbasePersistenUnitEnv;
import cn.ilikes.tools.hbase.jpa.clients.AbClient;
import cn.ilikes.tools.hbase.jpa.persistences.cache.Cache;
import cn.ilikes.tools.hbase.jpa.persistences.cache.JPAFirstCache;
import cn.ilikes.tools.hbase.jpa.persistences.transactions.JPAHBaseTransaction;
import cn.ilikes.tools.logs.Loggerfactory;

public abstract class AbstractContext implements Context {

	private static Logger logger = Loggerfactory.instance(AbstractContext.class);

	private JPAHbasePersistenUnitEnv hbasePersistenUnitEnv;

	private AbClient client;

	public AbstractContext(JPAHbasePersistenUnitEnv hbasePersistenUnitEnv, AbClient clients) {
		super();
		this.hbasePersistenUnitEnv = hbasePersistenUnitEnv;
		this.client = clients;
	}

	private Cache cache = new JPAFirstCache();

	private Stack<Operation<?>> qperationsStack = new Stack<Operation<?>>();

	@Override
	public void init() {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.info(logger, "JPA HBase context   init   ");

	}

	public Cache getCache() {
		return cache;
	}

	public Stack<Operation<?>> getQperationsStack() {
		return qperationsStack;
	}

	public EntityTransaction createEntityTransaction() {
		EntityTransaction entityTransaction = new JPAHBaseTransaction(this);
		return entityTransaction;
	}

	@Override
	public <V> Object operation(Operation<V> operation) {

		Object value = operation.exec();
		qperationsStack.push(operation);

		//		if (result) {
		//		} else {
		//			throw new ContextRuntimeException(" JPA HBase Context Operation not success !  " + operation.getOperationType());
		//		}

		return value;
	}

	@Override
	public void rollback() {

		do {
			Operation<?> qperations = qperationsStack.pop();
			qperations.rollback();
		} while (!qperationsStack.isEmpty());

	}

	@Override
	public void commit() {
		do {
			Operation<?> qperations = qperationsStack.pop();
			qperations.flush();
		} while (!qperationsStack.isEmpty());

		AbClient client = getClient();
		client.flush();

	}

	@Override
	public void clear() {

	}

	public JPAHbasePersistenUnitEnv getHbasePersistenUnitEnv() {
		return hbasePersistenUnitEnv;
	}

	public AbClient getClient() {
		return client;
	}

	@Override
	public void flush() {
		AbClient client = getClient();
		client.flush();

	}

	public <K, Node> void putCache(K key, Node value) {
		cache.put(key, value);
	}

	public <K, Node> Node getCache(K key) {
		return cache.get(key);
	}

}
